



#ifndef OHOS_CAMERA_CAPTURER_H_
#define OHOS_CAMERA_CAPTURER_H_

#include "media/base/video_common.h"
#include "modules/video_capture/video_capture_impl.h"
#include "common_video/ohos/ohos_egl_render_context.h"
#include "common_video/ohos/ohos_video_buffer.h"

#include <ohcamera/camera.h>
#include <ohcamera/camera_manager.h>
#include <multimedia/image_framework/image/image_receiver_native.h>
#include <native_image/native_image.h>

#include <mutex>
#include <map>

namespace webrtc {
namespace videocapturemodule {

class OhosImageReceiveOn {
public:
    virtual int32_t ImageReceiverCallback(OH_ImageReceiverNative *receiver) = 0;
    int32_t InitImageReceiver(int width, int height);
    int32_t ImageReceiverRelease();
    static uint64_t GetImageReceiverSurfaceID(OH_ImageReceiverNative *receiver);
    uint64_t GetImageReceiverID();
    OH_ImageReceiverNative* GetImageReceiver();

private:
    uint64_t imageReceiverID_ {0};
    OH_ImageReceiverNative *imageReceiverNative_ {nullptr};
};

class VideoCaptureOhos;
class ImageReceiverOnManager {
public:
    static ImageReceiverOnManager& GetInstance();
    int32_t AddImageReceiverOn(uint64_t id, OhosImageReceiveOn* imgRecOn);
    int32_t DelImageReceiverOn(uint64_t id);
    OhosImageReceiveOn* GetReceiverOnCb(const uint64_t imageReceiverID);
    static void ImageReceiverCallback(OH_ImageReceiverNative* receiver);
    VideoCaptureOhos* cameraCapturer_ {nullptr}; //ohos camera do not support multi instance now

private:
    ImageReceiverOnManager() {}
    ~ImageReceiverOnManager() {}
    ImageReceiverOnManager(const ImageReceiverOnManager&) {}
    ImageReceiverOnManager& operator=(const ImageReceiverOnManager&) = delete;
    std::mutex map_mutex_;
    std::map<uint64_t, OhosImageReceiveOn* > receiverOnMap_;
};


class VideoCaptureOhos : public OhosImageReceiveOn
                       , public VideoCaptureImpl{

public:
  enum CaptureType {
      SURFACE = 0,
      BUFFER
  };

public:
  VideoCaptureOhos(CaptureType type = CaptureType::SURFACE, bool enable_auto_rotation = false);
  int32_t Init(const char* device_id);
  int32_t StartCapture(const VideoCaptureCapability& capability) override;
  int32_t StopCapture() override;

  bool CaptureStarted() override;
  int32_t CaptureSettings(VideoCaptureCapability& settings) override;

  int32_t SetCaptureRotation(VideoRotation rotation) override;
  void UpdateSensorOrientation();

  bool ImageReceiverOn(uint8_t *buffer, int32_t width, int32_t height, int32_t stride, size_t bufferSize);
  int32_t ImageReceiverCallback(OH_ImageReceiverNative *receiver) override;
  void OnCameraStatusChange(Camera_Status status);

  Camera_Manager* camera_manager_ {nullptr};

protected:
  ~VideoCaptureOhos() override;

private:
    /* RenderContext(EglContext EglDisplay)创建和销毁 */
    bool InitRenderContext();
    int32_t DestroyRenderContext();

    /* NativeWindow创建和销毁 */
    bool CreateNativeWindow();
    int32_t DestroyNativeWindow();

    /* NativeImage创建和销毁，需要使用eglSurface,textureID */
    bool CreateNativeImage();
    int32_t DestroyNativeImage();

    /* NativeImage回调函数 */
    static void OnNativeImageFrameAvailable(void *data);
    int32_t OnNativeFrameAvailable();

    OHNativeWindow *nativeWindow_ {nullptr};
    OH_NativeImage *nativeImage_ {nullptr};
    GLuint nativeImageTextureID_ {0U};
    EGLSurface eglSurface_ {EGL_NO_SURFACE};
    OH_OnFrameAvailableListener nativeImageFrameAvailableListener_{nullptr, nullptr};
    OhosVideoBuffer::TextureBuffer textureBuffer_;
    std::unique_ptr<EGLRenderContext> gl_context_;

private:
  int32_t CameraInputCreateAndOpen();
  int32_t VideoOutputCreate(int width, int height, int fps);
  int32_t PreviewOutputCreate(int width, int height, int fps);
  int32_t CaptureSessionCreate();
  // Set capture fps by system api.
  int32_t SetCaptureFps(int fps);
  int32_t CameraInputRelease();
  int32_t VideoOutputRelease();
  int32_t PreviewOutputRelease();
  int32_t CaptureSessionRelease();
  int32_t DeleteCameraOutputCapability();
  int32_t DeleteCameras();
  int32_t DeleteCameraManage();
  int GetFrameRotation();
  // more recommend to use preview output mode 
  bool is_video_output_ {false};
  bool is_init_ {false};
  bool is_camera_started_ {false};
  Camera_Device* cameras_ {nullptr};
  Camera_Input* camera_input_ {nullptr};
  Camera_PreviewOutput* preview_output_ {nullptr};
  Camera_VideoOutput* video_output_ {nullptr};
  uint32_t cameras_size_ {0};
  Camera_CaptureSession* capture_session_ {nullptr};
  Camera_OutputCapability* camera_output_capability_ {nullptr};
  const Camera_Profile* preview_profile_ {nullptr};
  const Camera_VideoProfile* video_profile_ {nullptr};
  uint32_t camera_dev_index_ {0};
  int rotation_ = webrtc::kVideoRotation_0;
  int sensor_orientation_ = 0;
  CaptureType captureType_ {CaptureType::SURFACE};
  int debug_log_counter_ = 0;
  int fps_ = 0;

  bool enable_auto_rotation_ = false;
};


}  // namespace videocapturemodule
}  // namespace webrtc

#endif //OHOS_CAMERA_CAPTURER_H_
